package com.ly.mp.biz.impl;

import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import com.ly.mp.biz.ITestService;
import com.ly.mp.dal.comm.annotation.MpDataSource;
import com.ly.mp.dal.comm.jdbc.PagedJdbcTemplate;
import com.ly.mp.dal.comm.jdbc.ReadWriteDataSourceDecision;

@Service
public class TestServicesImpl implements ITestService {
    private Logger log = LoggerFactory.getLogger(TestServicesImpl.class);
    @Autowired
    PagedJdbcTemplate pagedJdbcTemplate;
    @Autowired
    @Lazy
    ITestService testService;

    //测试写库
    @Override
    @Transactional(readOnly = false)
    @MpDataSource(value = "default")
    public Map<String, Object> queryByBillNoWrite(String billNo) {
        log.info("key:   ===   {}",ReadWriteDataSourceDecision.getDsKey());
        MapSqlParameterSource mapSqlParameterSource = new MapSqlParameterSource();
        mapSqlParameterSource.addValue("billNo", billNo);
        Map<String, Object> queryForMap = pagedJdbcTemplate.queryForMap("select t.* from t_eap_wf_process_runtime t where t.business_no = :billNo order by INITIATE_DATETIME desc", mapSqlParameterSource);
        
        log.info("queryForMap: {}", queryForMap);
        return queryForMap;
    }
    
    //测试读库
    @Override
    @Transactional(readOnly = true)
    @MpDataSource(value = "default")
    public Map<String, Object> queryByBillNoRead(String billNo) {
        log.info("key:   ===   {}",ReadWriteDataSourceDecision.getDsKey());
        MapSqlParameterSource mapSqlParameterSource = new MapSqlParameterSource();
        mapSqlParameterSource.addValue("billNo", billNo);
        Map<String, Object> queryForMap = pagedJdbcTemplate.queryForMap("select t.* from t_eap_wf_process_runtime t where t.business_no = :billNo order by INITIATE_DATETIME desc", mapSqlParameterSource);
        
        log.info("queryForMap: {}", queryForMap);
        return queryForMap;
    }
    
    //测试事务, 因为就一个写库, 又配置了事务管理器, 就很正常测试
    @Override
    @Transactional(rollbackFor = Exception.class, readOnly = false)
    @MpDataSource(value = "default")
    public int updateByBillNoWrite(String billNo, String status) {
        log.info("key:   ===   {}",ReadWriteDataSourceDecision.getDsKey());
        MapSqlParameterSource mapSqlParameterSource = new MapSqlParameterSource();
        mapSqlParameterSource.addValue("billNo", billNo);
        mapSqlParameterSource.addValue("status", status);
        
        int update = pagedJdbcTemplate.update("update t_eap_wf_process_runtime set PROCESS_STATUS = :status where BUSINESS_NO=:billNo", mapSqlParameterSource);
        log.info("update: {}", update);
        
        Assert.state(update <= 0, "更新成功,模拟报错测试回滚!");
        return update;
    }
    
    // 切换读库, 事务生效
    @Override
    @Transactional(rollbackFor = Exception.class, readOnly = false,transactionManager = "transactionManager")
    @MpDataSource(value = "default")
    public int midwaySwitch(String billNo, String status) {
        MapSqlParameterSource mapSqlParameterSource = new MapSqlParameterSource();
        testService.makeRead(billNo, status, mapSqlParameterSource);
        
        log.info("key3:   ===   {}",ReadWriteDataSourceDecision.getDsKey());
        mapSqlParameterSource.addValue("billNo", billNo);
        mapSqlParameterSource.addValue("status", status);
        
        int update = pagedJdbcTemplate.update("update t_eap_wf_process_runtime set PROCESS_STATUS = :status where BUSINESS_NO=:billNo", mapSqlParameterSource);
        log.info("update: {}", update);
        log.info("key4:   ===   {}",ReadWriteDataSourceDecision.getDsKey());
        
        Assert.state(update <= 0, "更新成功,模拟报错测试回滚!");
        return update;
    }

    @Transactional(rollbackFor = Exception.class, readOnly = true)
    @MpDataSource(value = "default",cascading = false)
    public int makeRead(String billNo, String status, MapSqlParameterSource mapSqlParameterSource) {
        ReadWriteDataSourceDecision.markRead("default");
        log.info("key1:   ===   {}",ReadWriteDataSourceDecision.getDsKey());

        mapSqlParameterSource.addValue("billNo", "CCBX2303130052");
        Map<String, Object> queryForMap = pagedJdbcTemplate.queryForMap("select t.* from t_eap_wf_process_runtime t where t.business_no = :billNo order by INITIATE_DATETIME desc", mapSqlParameterSource);
        log.info("queryForMap: {}", queryForMap);
        
        log.info("key2:   ===   {}",ReadWriteDataSourceDecision.getDsKey());
        return 0;
    }
    
    // 切换读库, 读的数据库没有配置管理器, 不会回滚, 但是写库是可以回滚的
    @Override
    @Transactional(rollbackFor = Exception.class, readOnly = false,transactionManager = "transactionManager")
    @MpDataSource(value = "default")
    public int midwaySwitchTow(String billNo, String status) {
        MapSqlParameterSource mapSqlParameterSource = new MapSqlParameterSource();
        ReadWriteDataSourceDecision.markRead("default");
        testService.makeWriteTow(billNo, status, mapSqlParameterSource);
        
        log.info("key3:   ===   {}",ReadWriteDataSourceDecision.getDsKey());
        mapSqlParameterSource.addValue("billNo", billNo);
        mapSqlParameterSource.addValue("status", status);
        
        int update = pagedJdbcTemplate.update("update t_eap_wf_process_runtime set PROCESS_STATUS = :status where BUSINESS_NO=:billNo", mapSqlParameterSource);
        log.info("update: {}", update);
        log.info("key4:   ===   {}",ReadWriteDataSourceDecision.getDsKey());
        
        Assert.state(update <= 0, "更新成功,模拟报错测试回滚!");
        return update;
    }

    // 可以更新, 只是异常就不能回滚了, 除非你配置了事务管理器
    // 这个名称有问题的, 后面如果你要那种读库也可以回滚的, 这个名称要重新设计下
    @Transactional(rollbackFor = Exception.class, readOnly = true,transactionManager = "transactionManagerTwo")
    @MpDataSource(value = "default",cascading = false)
    public int makeWriteTow(String billNo, String status, MapSqlParameterSource mapSqlParameterSource) {
        log.info("key1:   ===   {}",ReadWriteDataSourceDecision.getDsKey());

        mapSqlParameterSource.addValue("billNo", "CCBX2303130052");
        mapSqlParameterSource.addValue("status", "7");
        int update = pagedJdbcTemplate.update("update t_eap_wf_process_runtime set PROCESS_STATUS = :status where BUSINESS_NO=:billNo", mapSqlParameterSource);
        log.info("makeWriteTow update: {}", update);
        
        Assert.state(update <= 0, "更新成功,模拟报错测试回滚!");
        
        log.info("key2:   ===   {}",ReadWriteDataSourceDecision.getDsKey());
        return 0;
    }
    
}
